home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Palettes / MiscSwapKitPalette / MiscSwapKit.subproj / MiscSwapView.m < prev    next >
Encoding:
Text File  |  1995-04-12  |  7.5 KB  |  324 lines

  1. /* MiscSwapView.m
  2.  *
  3.  * This subclass of View is able to swap different views into itself. It's
  4.  * used to implement any kind of multipage windows. (Inspectors, Prefs...)
  5.  *
  6.  * For more interface-info see the header file. More in depth information
  7.  * can be found here in the source-code.
  8.  *
  9.  * Notes: There is one Cateogry for this class includes automatic swapping.
  10.  *
  11.  * Improved by:        Thomas Engel
  12.  * First changes:   24.01.1994 (Copyleft)
  13.  * Last modified:     25.09.1994
  14.  * Copyright (C) 1995 Thomas Engel
  15.  */
  16.  
  17. #import <apps/InterfaceBuilder.h>
  18. #import <misckit/MiscSwapView.h>
  19.  
  20. // The following are for keeping track of versions when archiving instances
  21. // of this class. If you change the write: method, make sure to
  22. // bump up the version below and make the appropriate changes to the read:
  23. // method so all previously archived instances will be unarchivable.
  24.  
  25. #define MISC_SV_VERSION 0
  26. #define MISC_SV_CLASSNAME "MiscSwapView"
  27.  
  28.  
  29. @implementation MiscSwapView
  30.  
  31. + initialize
  32. {
  33.     // Initialize the current version number which is used when archiving 
  34.     // objects. This way we will be able to read all versions if we are 
  35.     // careful.
  36.  
  37.     if (self == [MiscSwapView class])
  38.         [self setVersion: MISC_SV_VERSION];
  39.         
  40.     return self;
  41. }
  42.  
  43. - init
  44. {
  45.     NXRect theFrame = {{0.0, 0.0}, {0.0, 0.0}};
  46.     return [self initFrame:&theFrame];
  47. }
  48.  
  49. - initFrame:(const NXRect *)frameRect
  50. {
  51.     // Designated initilizer. We will set allow resizing by default and
  52.     // we will draw in Lightgray if we have to swap 'nil' in.
  53.  
  54.     self = [super initFrame:frameRect];
  55.     if( !self ) return self;
  56.  
  57.     contentView = nil;
  58.     contentViewsHomeView = nil;
  59.     [self setDelegate: nil];
  60.     trigger = nil;
  61.     currentController = nil;
  62.     backgroundGray = NX_LTGRAY;
  63.     [self setAutoresizeSubviews:YES];
  64.     useBuffering = NO;
  65.     
  66.     // Well the ByObject Category want's some other defaults too.
  67.     
  68.     controllers = [List new];     
  69.      [self setTagComparison:YES];
  70.  
  71.     return self;
  72. }
  73.  
  74. - free
  75. {
  76.     // We do not free the contentsControllers of this list! Well we didin't
  77.     // allocate them..but maybe we should free them...hmmm. I'm not sure yet.
  78.     
  79.     [controllers free];
  80.     return [super free];
  81. }
  82.  
  83. - setDelegate:(id)anObject
  84. {
  85.     delegate = anObject;
  86.     return self;
  87. }
  88.  
  89. - delegate
  90. {
  91.     return delegate;
  92. }
  93.  
  94. - setBackgroundGray:(float)aGray
  95. {
  96.     backgroundGray = aGray;
  97.     return self;
  98. }
  99.  
  100. - (float)backgroundGray
  101. {
  102.     return backgroundGray;
  103. }
  104.  
  105. - setUseBuffering:(BOOL)flag
  106. {
  107.     useBuffering = flag;
  108.     return self;
  109. }
  110.  
  111. - (BOOL)doesUseBuffering
  112. {
  113.     return useBuffering;
  114. }
  115.  
  116. - setContentView:aView
  117. {
  118.      // This is the real method !! 
  119.      // Here we process the finding of the swapping and resizing.
  120.     // If the new view is different from our current contentView we should
  121.     // put the current back where it came from.
  122.     
  123.     NXRect    theFrame;
  124.     id        contentViewsHomeWindow;
  125.     int        gState = 0;
  126.     
  127.     if( aView != contentView )
  128.     {
  129.         if( contentView && contentViewsHomeView )
  130.         {
  131.             [contentView removeFromSuperview];
  132.             [contentViewsHomeView addSubview:contentView];
  133.             [contentView moveTo:contentViewsHomeRect.origin.x
  134.                                :contentViewsHomeRect.origin.y];
  135.             [contentView sizeTo:contentViewsHomeRect.size.width
  136.                                :contentViewsHomeRect.size.height];
  137.         }
  138.     
  139.         // No real subview? So clean up the background. This is done by
  140.         // filling the view bounds with the backgroundGray we did set.
  141.     
  142.         contentView = aView;
  143.         
  144. //        if( !contentView )
  145. //        {
  146. //            contentViewsHomeView = nil;
  147. //        }
  148.             [self lockFocus];
  149.                 PSsetgray( backgroundGray );
  150.                 NXRectFill(&bounds);
  151.             [self unlockFocus];
  152.         if( !contentView )
  153.         {
  154.             contentViewsHomeView = nil;
  155.         }
  156.  
  157.  
  158.         // Otherwise we have a new subview so lets remove it form its home-
  159.         // window, resize it and align it to our 0,0 corner.
  160.         // If we have to use buffered composing we will now display our self
  161.         // but we will compose into the screen. This might cause problems with
  162.         // views that have to be resized.
  163.         
  164.         else
  165.         {
  166.             // If we use buffering then lets compose the views offscreen
  167.             // if they have no gState which meant that they haven't been
  168.             // drawn yet.
  169.             // Let's ensure the windows are always retained and non deffered.
  170.             // This make easy-offscreen drawing possible.
  171.             
  172.             contentViewsHomeWindow = [contentView window];
  173.             contentViewsHomeView = [contentView superview];
  174.             [contentView getFrame:&contentViewsHomeRect];
  175.  
  176.             if( useBuffering )
  177.             {
  178.                 [contentViewsHomeWindow setBackingType:NX_RETAINED];
  179.                  
  180.                 // Now lets get the views position inside its home.
  181.                 // We also need a gState to be able to do the fast copying.
  182.                 
  183.                 [contentView getFrame:&theFrame];
  184.                 gState = [contentViewsHomeView gState];
  185.                 if( !gState )
  186.                 {
  187.                     [contentViewsHomeView allocateGState];
  188.                     [contentViewsHomeView display];
  189.                     gState = [contentViewsHomeView gState];                
  190.                 }
  191.                 NXPing();
  192.             }
  193.             
  194.             // The view reorganication is always the same.
  195.             // Resizing is only applyed when we don't use buffering!
  196.             
  197.             [contentView removeFromSuperview];
  198.             [self addSubview:contentView];
  199.             [contentView moveTo:0.0 :0.0];
  200.             
  201.             // The displaying might come with a simple redraw or a quick
  202.             // composing by copying from the offscreen buffer.
  203.             
  204.             if( useBuffering && gState )
  205.             {
  206.                 // We will fill our background first to allow swapping of
  207.                 // views that don't have the same size.
  208.                 // Because they are not resized here to cover the whole
  209.                 // area its a must to clear the whole scene before!
  210.                 
  211.                 [self lockFocus];
  212.                  PSsetgray(backgroundGray);
  213.                  NXRectFill(&bounds);
  214.                 PScomposite( (float)theFrame.origin.x,
  215.                               (float)theFrame.origin.y,
  216.                              (float)theFrame.size.width,
  217.                              (float)theFrame.size.height,
  218.                              (int)gState,
  219.                              (float)0.0,
  220.                              (float)0.0,
  221.                              (int)NX_COPY );
  222.                 [self unlockFocus];
  223.             }
  224.             else
  225.             {
  226.                 [contentView sizeTo:bounds.size.width :bounds.size.height];
  227.                 [self display];
  228.             }
  229.         }
  230.         // Let the windowServer catch up to the changes we made (yawn...)
  231.         // And show our nice new window
  232.         
  233.         NXPing();
  234.         [[self window] flushWindow];
  235.     }
  236.     return self;
  237. }
  238.  
  239. - contentView
  240. {
  241.     return contentView;
  242. }
  243.  
  244. - contentViewsHomeView;
  245. {
  246.     return contentViewsHomeView;
  247. }
  248.  
  249. - write:(NXTypedStream *)stream
  250. {
  251.     [super write: stream];
  252.     NXWriteObjectReference (stream, contentView);
  253.     NXWriteObjectReference (stream, contentViewsHomeView);
  254.     NXWriteObjectReference (stream, delegate);
  255.     NXWriteTypes (stream, "fc", &backgroundGray, &useBuffering);
  256.     NXWriteObjectReference (stream, trigger);
  257.     NXWriteType (stream, "c", &tagComparison);
  258.  
  259.     return self;
  260. }
  261.  
  262. - read:(NXTypedStream *)stream
  263. {
  264.   int  version;
  265.   
  266.     [super read: stream];
  267.     
  268.     version = NXTypedStreamClassVersion(stream, MISC_SV_CLASSNAME);
  269.     
  270.     switch (version)
  271.     {
  272.       case 0:
  273.         contentView = NXReadObject (stream);
  274.         contentViewsHomeView = NXReadObject (stream);
  275.         delegate = NXReadObject (stream);
  276.         NXReadTypes (stream, "fc", &backgroundGray, &useBuffering);
  277.         trigger = NXReadObject (stream);
  278.         NXReadType (stream, "c", &tagComparison);
  279.         break;
  280.         
  281.       default:
  282.           break;
  283.     }
  284.  
  285.     return self;
  286. }
  287.  
  288. - awake
  289. {
  290.     [super awake];
  291.     currentController = nil;
  292.     controllers = [List new];
  293.  
  294.     return self;
  295. }
  296.  
  297. - drawSelf:(const NXRect *)rects :(int)rectCount
  298. {
  299.     // As long as you have a trigger connected to the trigger outlet, this
  300.     // should select an initial view for you.
  301.  
  302.     if( contentView == nil )
  303.     {
  304.         [self swapContentView:[self trigger] ];
  305.     }
  306.     return self;
  307. }
  308.  
  309.  
  310. @end
  311.  
  312. /*
  313.  * History: 25.09.94 Added archiving. (read:, write: awake, initialize)
  314.  *                     Also added drawSelf:: so it would select an initial view.
  315.  *
  316.  *            24.02.94 Added Greg's quick composing.
  317.  *
  318.  *            24.01.94 Redesign from my old swapView. Added Buffering.
  319.  *
  320.  *            21.01.94 Added the resizing job the Greg's swapView.
  321.  *
  322.  * 
  323.  * Bugs: - Could be. Yes.
  324.  */